home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / crossedit / CrEdit.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  28KB  |  1,093 lines

  1.  
  2. #include "Defines.h"
  3. #include "Ansi.h"
  4. #include "Xaw.h"
  5. #include <X11/IntrinsicP.h>
  6. #include <X11/StringDefs.h>
  7.  
  8. #include "global.h"
  9. #include "debug.h"
  10. #include "xio.h"
  11.  
  12. #include "Cnv.h"
  13. #include "CrEditP.h"
  14. #include "CrUtil.h"
  15.  
  16. extern    Pixmap *pixmaps;       /* list of pixmaps */
  17.  
  18. /**********************************************************************
  19.  * resources
  20.  **********************************************************************/
  21.  
  22. static XtResource resources[] = {
  23. #define Offset(field) XtOffsetOf(CrEditRec, crEdit.field)
  24.     { 
  25.     XtNinsertCallback,
  26.     XtCInsertCallback,
  27.     XtRCallback,
  28.     sizeof(XtCallbackList),
  29.     Offset(insertCallbacks),
  30.     XtRCallback,
  31.     NULL
  32.     },{
  33.     XtNselectCallback,
  34.     XtCSelectCallback,
  35.     XtRCallback,
  36.     sizeof(XtCallbackList),
  37.     Offset(selectCallbacks),
  38.     XtRCallback,
  39.     NULL
  40.     },{
  41.     XtNpropsCallback,
  42.     XtCPropsCallback,
  43.     XtRCallback,
  44.     sizeof(XtCallbackList),
  45.     Offset(propsCallbacks),
  46.     XtRCallback,
  47.     NULL
  48.     },{
  49.     XtNdeleteCallback,
  50.     XtCDeleteCallback,
  51.     XtRCallback,
  52.     sizeof(XtCallbackList),
  53.     Offset(deleteCallbacks),
  54.     XtRCallback,
  55.     NULL
  56.     },{
  57.     XtNalignCallback,
  58.     XtCAlignCallback,
  59.     XtRCallback,
  60.     sizeof(XtCallbackList),
  61.     Offset(alignCallbacks),
  62.     XtRCallback,
  63.     NULL
  64.     },{
  65.     XtNfeedCallback,
  66.     XtCFeedCallback,
  67.     XtRCallback,
  68.     sizeof(XtCallbackList),
  69.     Offset(feedCallbacks),
  70.     XtRCallback,
  71.     NULL
  72.     },{
  73.     XtNmap,
  74.     XtCMap,
  75.     XtRPointer,
  76.     sizeof(XtPointer),
  77.     Offset(map),
  78.     XtRPointer,
  79.     NULL
  80.     },{
  81.     XtNstacking,
  82.     XtCStacking,
  83.     XtRInt,
  84.     sizeof(int),
  85.     Offset(stacking),
  86.     XtRImmediate,
  87.     (XtPointer)0
  88.     },{
  89.     XtNshow_weak_walls,
  90.     XtCShow_weak_walls,
  91.     XtRInt,
  92.     sizeof(int),
  93.     Offset(show_weak_walls),
  94.     XtRImmediate,
  95.     (XtPointer)0
  96.     },{
  97.     XtNselectArea,
  98.     XtCSelectArea,
  99.     XtRBoolean,
  100.     sizeof(Boolean),
  101.     Offset(selectArea),
  102.     XtRBoolean,
  103.     (XtPointer)NULL,
  104.     }
  105. #undef offset
  106. };
  107.  
  108. /**********************************************************************
  109.  * declarations
  110.  **********************************************************************/
  111.  
  112. static void UpdatePosition (Widget w, int x, int y,Boolean inv);
  113. static void ClassInitialize();
  114. static void Initialize(Widget req,Widget new,Arg args[],Cardinal *num);
  115. static void Destroy(Widget w);
  116. static void Resize(Widget w);
  117. static void Redisplay(Widget w,XEvent *event,Region region);
  118. static Boolean SetValues(Widget cur,Widget req,Widget new,
  119.              Arg args[],Cardinal *num);
  120.  
  121. #define EmptyObject "editor_archetype"
  122.  
  123. /**********************************************************************
  124.  * actions & translations
  125.  **********************************************************************/
  126.  
  127. static void InsertAc ( Widget w, XEvent * event, 
  128.               String * argv, Cardinal * argc );
  129. static void DeleteAc ( Widget w, XEvent * event, 
  130.               String * argv, Cardinal * argc );
  131. static void PropsAc ( Widget w, XEvent * event, 
  132.               String * argv, Cardinal * argc );
  133. static void MoveAc ( Widget w, XEvent * e, 
  134.             String * argv, Cardinal * argc );
  135. static void ResizeAc ( Widget w, XEvent * e, 
  136.               String * argv, Cardinal * argc );
  137. static void ScrollAc ( Widget w, XEvent * e, 
  138.               String * argv, Cardinal * argc );
  139. static void SelectBeginAc ( Widget w, XEvent * e, 
  140.                String * argv, Cardinal * argc );
  141. static void SelectExpandAc ( Widget w, XEvent * e, 
  142.                 String * argv, Cardinal * argc );
  143. static void SelectEndAc ( Widget w, XEvent * e, 
  144.              String * argv, Cardinal * argc );
  145. static void FeedAc ( Widget w, XEvent * e, 
  146.             String * argv, Cardinal * argc );
  147.  
  148. XtActionsRec actions[] = {
  149.   {"Insert", InsertAc},
  150.   {"SelectBegin", SelectBeginAc},
  151.   {"SelectExpand", SelectExpandAc},
  152.   {"SelectEnd", SelectEndAc},
  153.   {"Props", PropsAc},
  154.   {"Delete", DeleteAc},
  155.   {"Feed", FeedAc},
  156.   {"Move", MoveAc},
  157.   {"Resize", ResizeAc},
  158.   {"Scroll", ScrollAc},
  159. };
  160.  
  161. static char translations[] = "\
  162.     <Btn1Up>:         Insert(archetype) \n\
  163.     <Btn1Motion>:     Insert(archetype) \n\
  164.     Ctrl<Btn2Up>:     Feed(coordinate) \n\
  165.     Ctrl<Btn2Motion>: Feed(coordinate) \n\
  166.     Shift<Btn2Up>:    Props() \n\
  167.     None<Btn2Down>:   SelectBegin() \n\
  168.     None<Btn2Motion>: SelectExpand() \n\
  169.     None<Btn2Up>:     SelectEnd() \n\
  170.     <Btn3Down>:       Delete(archetype) \n\
  171.     <Btn3Motion>:     Delete(archetype) \n\
  172.         Ctrl<Key>Right:   Resize(right) \n\
  173.     Ctrl<Key>Left:    Resize(left) \n\
  174.         Ctrl<Key>Down:    Resize(down) \n\
  175.     Ctrl<Key>Up:      Resize(up) \n\
  176.         Shift<Key>Right:  Scroll(right) \n\
  177.     Shift<Key>Left:   Scroll(left) \n\
  178.         Shift<Key>Down:   Scroll(down) \n\
  179.     Shift<Key>Up:     Scroll(up) \n\
  180.         <Key>Right:       Move(right) \n\
  181.     <Key>Left:        Move(left) \n\
  182.         <Key>Down:        Move(down) \n\
  183.     <Key>Up:          Move(up) \n\
  184. ";
  185.  
  186. /**********************************************************************
  187.  * class record
  188.  **********************************************************************/
  189.  
  190. CrEditClassRec crEditClassRec = {
  191.   { /* core fields */
  192.     /* superclass        */    (WidgetClass)&widgetClassRec,
  193.     /* class_name        */    "CrEdit",
  194.     /* widget_size        */    sizeof(CrEditRec),
  195.     /* class_initialize        */    ClassInitialize,
  196.     /* class_part_initialize    */    NULL,
  197.     /* class_inited        */    FALSE,
  198.     /* initialize        */    Initialize,
  199.     /* initialize_hook        */    NULL,
  200.     /* realize            */    XtInheritRealize,
  201.     /* actions            */    actions,
  202.     /* num_actions        */    XtNumber(actions),
  203.     /* resources        */    resources,
  204.     /* num_resources        */    XtNumber(resources),
  205.     /* xrm_class        */    NULLQUARK,
  206.     /* compress_motion        */    TRUE,
  207.     /* compress_exposure    */    TRUE,
  208.     /* compress_enterleave    */    TRUE,
  209.     /* visible_interest        */    FALSE,
  210.     /* destroy            */    Destroy,
  211.     /* resize            */    Resize,
  212.     /* expose            */    Redisplay,
  213.     /* set_values        */    SetValues,
  214.     /* set_values_hook        */    NULL,
  215.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  216.     /* get_values_hook        */    NULL,
  217.     /* accept_focus        */    NULL,
  218.     /* version            */    XtVersion,
  219.     /* callback_private        */    NULL,
  220.     /* tm_table            */    translations,
  221.     /* query_geometry        */    XtInheritQueryGeometry,
  222.     /* display_accelerator    */    XtInheritDisplayAccelerator,
  223.     /* extension        */    NULL
  224.   },
  225.   { /* crEdit fields */
  226.     /* empty            */    0
  227.   }
  228. };
  229.  
  230. WidgetClass crEditWidgetClass = (WidgetClass)&crEditClassRec;
  231.  
  232. /**********************************************************************
  233.  * inner functions 
  234.  **********************************************************************/
  235.  
  236. /*
  237.  *
  238.  */
  239. static void SegToRec(XSegment *seg,XRectangle *rec)
  240. {
  241.     /*** calculate rectangle ***/
  242.     rec->x = seg->x1 < seg->x2 ? seg->x1 : seg->x2;
  243.     rec->y = seg->y1 < seg->y2 ? seg->y1 : seg->y2;
  244.     rec->width = abs(seg->x1 - seg->x2) + 1;
  245.     rec->height = abs(seg->y1 - seg->y2) + 1;
  246. }
  247.  
  248. static void SetSize(Widget w)
  249. {
  250.     CrEditWidget self = (CrEditWidget)w;
  251.     XtWidgetGeometry request,reply;
  252.     /*Dimension width,height,rWidth,rHeight;*/
  253.  
  254.     /*** determine size to ask for ***/
  255.     if(self->crEdit.map) {
  256.     request.width = self->crEdit.map->mapx * self->crEdit.fontSize;
  257.     request.height = self->crEdit.map->mapy * self->crEdit.fontSize;
  258.     } else {
  259.     request.width = self->crEdit.fontSize;
  260.     request.height = self->crEdit.fontSize;
  261.     }
  262.     request.x = request.y = 0;
  263.     request.request_mode = CWWidth | CWHeight;
  264.     
  265.     /*** ask it ***/
  266.     switch(XtMakeGeometryRequest(w,&request,&reply)) {
  267.     case XtGeometryYes:
  268.     break;
  269.     case XtGeometryNo:
  270.     debug1 ("%s: May not change my geometry\n",XtName(w));
  271.     break;
  272.     case XtGeometryAlmost:
  273.     XtMakeGeometryRequest(w,&reply,&reply);
  274.     break;
  275.     default:
  276.     CnvDie(w,"Unknown geometry request return");
  277.     break;
  278.     };
  279.     /*
  280.     XSendEvent(XtDisplay(w),XtWindow(w),False,ResizeRequest,NULL);
  281.     */
  282.     debug3("%s: setting widget size to %dx%d\n",XtName(w),self->core.width,
  283.        self->core.height);
  284. }
  285.     
  286. /**********************************************************************
  287.  **********************************************************************/
  288.  
  289. #if defined (WIZARD_MODE)
  290.  
  291. static void AnimateCursor (Widget w, int x, int y) {
  292.     static int old_x, old_y;
  293.     static Cursor wizc[4];
  294.     static int cursors_initialized;
  295.  
  296.     int xd = x - old_x;
  297.     int yd = y - old_y;
  298.     int i; 
  299.     
  300.     if (use_pixmaps && XtIsRealized (w)) {    
  301.     if (!cursors_initialized) {         
  302.         archetype *wizu = find_archetype ("editcursor");
  303.  
  304.         if (!wizu)
  305.         return ; /* $%&$&#$% */
  306.  
  307.         for (i = 0; i < 4; i++)
  308.         wizc[i] =  XCreatePixmapCursor 
  309.             (XtDisplay(w), 
  310.              pixmaps[wizu->faces[i]], 
  311.              pixmaps[wizu->faces[i + 4]],
  312.              discolor, discolor + 12, 12, 12);
  313.         cursors_initialized++;
  314.     }
  315.     if (abs (xd) > abs (yd))
  316.         if (xd < 0)
  317.         XDefineCursor (XtDisplay(w), XtWindow(w), wizc[3]);
  318.         else
  319.         XDefineCursor (XtDisplay(w), XtWindow(w), wizc[1]);
  320.     else
  321.         if (yd < 0)
  322.         XDefineCursor (XtDisplay(w), XtWindow(w), wizc[0]);
  323.         else
  324.         XDefineCursor (XtDisplay(w), XtWindow(w), wizc[2]);
  325.     
  326.     old_x = x;
  327.     old_y = y;
  328.     }
  329.     return;
  330. }
  331. #else 
  332. #define AnimateCursor(w,x,y)
  333. #endif
  334.  
  335.  
  336. /**********************************************************************
  337.  * drawing functions
  338.  * hierarchy:
  339.  *   DrawRectangle DrawBorder
  340.  *   UpdatePosition
  341.  *   DrawObject
  342.  **********************************************************************/
  343.  
  344. /*
  345.  * inv : draw inverse colored object if True
  346.  */
  347.  
  348.  
  349. /*
  350.  * member: update object stack at point in map
  351.  * x,y   : point
  352.  * inv   : draw inverse
  353.  */
  354. static void UpdatePosition (Widget w, int x, int y,Boolean inv)
  355. {
  356.     CrEditWidget self = (CrEditWidget)w;
  357.     object *op;
  358.     int i;
  359.  
  360.     if(out_of_map(self->crEdit.map,x,y)) return; 
  361.     
  362.     if (self->crEdit.stacking) {
  363.     /* stacking mode */
  364.     float xb, yb;
  365.     XClearArea (XtDisplay(w), XtWindow(w), 
  366.             x * self->crEdit.fontSize, 
  367.             y * self->crEdit.fontSize, 
  368.             self->crEdit.fontSize, 
  369.             self->crEdit.fontSize, False);
  370.     for (i = 0, op = get_map_ob (self->crEdit.map, x, y); 
  371.          op;
  372.          i++, op = op->above);
  373.     if (i > 0) {
  374.         int diff = self->crEdit.fontSize - FONTSIZE;
  375.         int depth = diff / STACK_MIN + 1;
  376.         float dist = 0;
  377.  
  378.         if (depth < 1)
  379.         depth = 1;
  380.         for (op = get_map_ob (self->crEdit.map, x, y); i > depth; i--)
  381.         op = op->above;
  382.  
  383.         i--;
  384.         if (i) {
  385.         dist = (diff - 1) / (float)i;
  386.         if (dist > STACK_MAX)
  387.             dist = STACK_MAX;
  388.         }
  389.  
  390.         xb = diff + x * self->crEdit.fontSize - 1;
  391.         yb = diff + y * self->crEdit.fontSize - 1;
  392.  
  393.         while (op) {
  394.         New_Face f;
  395.         if (QUERY_FLAG(op, FLAG_TEAR_DOWN) && self->crEdit.show_weak_walls)
  396.             f=new_faces[op->arch->faces[op->arch->animations/2]];
  397.         else f = *op->face;
  398.         if (inv  == True) {
  399.             int tmp = f.fg;
  400.             f.fg = f.bg;
  401.             f.bg = tmp;
  402.         }
  403.         FaceDraw (w, self->crEdit.gc, &f, xb, yb);
  404.  
  405.         if (HAS_COLOUR(w)) {
  406.             XSetForeground(XtDisplay(w), self->crEdit.gc, 
  407.                    BlackPixelOfScreen(XtScreen(w)));
  408.         }
  409.         XDrawRectangle (XtDisplay(w), 
  410.                 XtWindow(w), self->crEdit.gc,
  411.                 (int) xb, (int) yb, FONTSIZE -1, FONTSIZE -1);
  412.         xb -= dist;
  413.         yb -= dist;
  414.         op = op->above;
  415.         }
  416.     }
  417.     } else { /* Normal map drawing routine */
  418.         New_Face f;
  419.         if (color_pix) {
  420.           f = *(get_map_floor (self->crEdit.map, x, y)->face);
  421.           FaceDraw (w, self->crEdit.gc, &f,
  422.                     x * self->crEdit.fontSize,
  423.                     y * self->crEdit.fontSize);
  424.     }
  425.     op=get_map_ob(self->crEdit.map, x, y);
  426.     while (op && op->above) op=op->above;
  427.     if (!op) f=*blank_face;
  428.     else if (QUERY_FLAG(op, FLAG_TEAR_DOWN) && self->crEdit.show_weak_walls)
  429.         f=new_faces[op->arch->faces[op->arch->animations/2]];
  430.  
  431.     else f = *op->face;
  432.  
  433.     if (inv  == True) {
  434.         int tmp = f.fg;
  435.         f.fg = f.bg;
  436.         f.bg = tmp;
  437.     }
  438.     FaceDraw (w, self->crEdit.gc, &f, 
  439.           x * self->crEdit.fontSize, 
  440.           y * self->crEdit.fontSize);
  441.     }
  442.     return;
  443. }
  444.  
  445. /*
  446.  * member: draw filled rectangle
  447.  * rec   : rectangle
  448.  * inv   : True = inverse
  449.  */
  450. static void DrawRectangle(Widget w,XRectangle area,Boolean inv)
  451. {
  452.     CrEditWidget self = (CrEditWidget)w;
  453.     int i, j;
  454.  
  455.     for (j = area.x; 
  456.      j < area.x + area.width &&  j < self->crEdit.map->mapx; 
  457.      j++) {
  458.     for (i = area.y; 
  459.          i < area.y + area.height && i < self->crEdit.map->mapy; 
  460.          i++) {
  461.         UpdatePosition (w,j,i,inv);
  462.     }
  463.     }
  464. }
  465.  
  466. /*
  467.  * member: draw open square
  468.  * seg   : start and end points of square
  469.  * inv   : border of square are inversed
  470.  */
  471. static void DrawBorder(Widget w,XSegment seg,Boolean inv)
  472. {
  473.     CrEditWidget self = (CrEditWidget)w;
  474.     int i,x1,x2,y1,y2;
  475.     
  476.     x1 = seg.x1 < seg.x2 ? seg.x1 : seg.x2;
  477.     y1 = seg.y1 < seg.y2 ? seg.y1 : seg.y2;
  478.     x2 = abs(seg.x1 - seg.x2) + x1;
  479.     y2 = abs(seg.y1 - seg.y2) + y1;
  480.  
  481.     if(x1 > self->crEdit.map->mapx ||
  482.        x2 > self->crEdit.map->mapx ||
  483.        y1 > self->crEdit.map->mapy ||
  484.        y2 > self->crEdit.map->mapy) return;
  485.  
  486.     if (inv) {
  487.     XDrawRectangle (XtDisplay(w), XtWindow(w), 
  488.             DefaultGC(XtDisplay(w), XScreenNumberOfScreen(XtScreen(w))), 
  489.             x1 * self->crEdit.fontSize, 
  490.             y1 * self->crEdit.fontSize, 
  491.             (x2 - x1 + 1) * self->crEdit.fontSize - 1, 
  492.             (y2 - y1 + 1) * self->crEdit.fontSize - 1);
  493.     XDrawRectangle (XtDisplay(w), XtWindow(w), 
  494.             DefaultGC(XtDisplay(w), XScreenNumberOfScreen(XtScreen(w))), 
  495.             x1 * self->crEdit.fontSize + 1, 
  496.             y1 * self->crEdit.fontSize + 1, 
  497.             (x2 - x1 + 1) * self->crEdit.fontSize - 3, 
  498.             (y2 - y1 + 1) * self->crEdit.fontSize - 3);
  499.     } else {
  500.  
  501.     for(i=x1; 
  502.     i <= x2; 
  503.     i++) {
  504.     UpdatePosition(w,i,seg.y1,inv);
  505.         if (y1 != y2)
  506.     UpdatePosition(w,i,seg.y2,inv);
  507.     }
  508.     for(i=y1 + 1; 
  509.         i <= (y2 - 1);
  510.     i++) {
  511.     UpdatePosition(w,seg.x1,i,inv);
  512.         if (x1 != x2)
  513.     UpdatePosition(w,seg.x2,i,inv);
  514.     }
  515.     }
  516. }
  517.  
  518. /*
  519.  * member:
  520.  * x,y   :
  521.  * return:
  522.  */
  523. static int CalcIndex (Widget w, int x, int y) {
  524.     CrEditWidget self = (CrEditWidget)w; 
  525.     object *op;
  526.     int i, j = 0;
  527.     int xp, yp;
  528.     float xb, yb;
  529.     
  530.     xp = x / self->crEdit.fontSize;
  531.     yp = y / self->crEdit.fontSize;
  532.  
  533.     if (out_of_map (self->crEdit.map, xp, yp))
  534.     return 0;
  535.  
  536.     for (i = 0, op = get_map_ob (self->crEdit.map, xp, yp); 
  537.      op;
  538.      i++, op = op->above);
  539.  
  540.     if (i > 0) {
  541.     int diff = self->crEdit.fontSize - FONTSIZE;
  542.     int depth = diff / STACK_MIN;
  543.     float dist = 0;
  544.     
  545.     if (depth == 0)
  546.         depth = 1;
  547.     if (i > depth)
  548.         i = depth;
  549.  
  550.     i--;
  551.     if (i) {
  552.         dist = (diff - 1) / (float)i;
  553.         if (dist > STACK_MAX)
  554.         dist = STACK_MAX;
  555.     }
  556.  
  557.     xb = self->crEdit.fontSize - i * dist;
  558.     yb = self->crEdit.fontSize - i * dist;
  559.  
  560.     x %= self->crEdit.fontSize;
  561.     y %= self->crEdit.fontSize;
  562.  
  563.     debug4 ("%dx%d %d %f\n", x, y, i, dist);
  564.     for (j = 0; j <= i; j++) {
  565.         if (x < xb && y < yb)    
  566.         break;
  567.         xb += dist;
  568.         yb += dist;
  569.     }
  570.     }
  571.     return (j);
  572. }
  573.  
  574. /*
  575.  * no borders drawing set
  576.  */
  577. static void BorderOff(Widget w)
  578. {
  579.     CrEditWidget self = (CrEditWidget)w;
  580.     self->crEdit.seg.x1 = 0;
  581.     self->crEdit.seg.y1 = 0;
  582.     self->crEdit.seg.x2 = 10000;
  583.     self->crEdit.seg.y2 = 10000;
  584. }
  585.  
  586. /**********************************************************************
  587.  * actions
  588.  **********************************************************************/
  589.  
  590. /* 
  591.  * action: insert object to map 
  592.  */
  593. static void InsertAc (Widget w, XEvent * event, 
  594.               String * argv, Cardinal * argc)
  595. {
  596.     CrEditWidget self = (CrEditWidget)w;
  597.     int x, y;
  598.     static int oldx, oldy;
  599.     struct CrEditCall call;
  600.  
  601.     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
  602.     x = event->xbutton.x / self->crEdit.fontSize;
  603.     y = event->xbutton.y / self->crEdit.fontSize;
  604.  
  605.     if(XtHasCallbacks(w,XtNinsertCallback) == XtCallbackHasNone) return;
  606.     /*** fill the call strcture ***/
  607.     call.rect.x = x;
  608.     call.rect.y = y;
  609.     call.rect.width = 0;
  610.     call.rect.height = 0;
  611.     call.map = self->crEdit.map;
  612.     call.z = self->crEdit.stacking ? 
  613.     CalcIndex (w,event->xbutton.x,event->xbutton.y) : 0;
  614.     
  615.     if (!(event->type == MotionNotify  && x == oldx && y == oldy)) {
  616.     XtCallCallbackList(w,self->crEdit.insertCallbacks,(XtPointer)&call);
  617.     }
  618.     oldx = x;
  619.     oldy = y;
  620. }
  621.  
  622. /*
  623.  * action: set begin of selection
  624.  */
  625. static void SelectBeginAc(Widget w, XEvent * event, 
  626.               String * argv, Cardinal * argc)
  627. {
  628.     CrEditWidget self = (CrEditWidget)w;
  629.     int x,y;
  630.  
  631.     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
  632.     if(!self->crEdit.selectArea) return;
  633.     DrawBorder(w,self->crEdit.seg,False);
  634.  
  635.     x = event->xbutton.x / self->crEdit.fontSize;
  636.     y = event->xbutton.y / self->crEdit.fontSize;
  637.  
  638.     debug2("SelectBeginAc() %dx%d\n",x,y);
  639.  
  640.     if(out_of_map(self->crEdit.map,x,y)) return;    
  641.  
  642.     self->crEdit.seg.x1 = self->crEdit.seg.x2 = x;
  643.     self->crEdit.seg.y1 = self->crEdit.seg.y2 = y;
  644.     DrawBorder(w,self->crEdit.seg,True);
  645. }
  646.  
  647. /*
  648.  * action: expand selection
  649.  */
  650. static void SelectExpandAc(Widget w, XEvent * event, 
  651.                String * argv, Cardinal * argc)
  652. {
  653.     CrEditWidget self = (CrEditWidget)w;
  654.     int x,y;
  655.     static int oldx, oldy;
  656.  
  657.     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
  658.     if(!self->crEdit.selectArea) return;
  659.  
  660.     x = event->xbutton.x / self->crEdit.fontSize;
  661.     y = event->xbutton.y / self->crEdit.fontSize;
  662.  
  663.     if (x >= self->crEdit.map->mapx )
  664.     x = self->crEdit.map->mapx - 1;
  665.     if (x < 0)
  666.     x = 0;
  667.  
  668.     if (y >= self->crEdit.map->mapy )
  669.     y = self->crEdit.map->mapy - 1;
  670.     if (y < 0)
  671.     y = 0;
  672.  
  673.     if (!(event->type == MotionNotify  && x == oldx && y == oldy)) {
  674.     DrawBorder(w,self->crEdit.seg,False);
  675.     self->crEdit.seg.x2 = x;
  676.     self->crEdit.seg.y2 = y;
  677.     DrawBorder(w,self->crEdit.seg,True);
  678.     }
  679.     oldx = x;
  680.     oldy = y;
  681. }
  682.  
  683. /*
  684.  * action: get end of selection
  685.  */
  686. static void SelectEndAc(Widget w, XEvent * event,
  687.             String * argv, Cardinal * argc)
  688. {
  689.     CrEditWidget self = (CrEditWidget)w;
  690.     int x,y;
  691.     struct CrEditCall call;
  692.  
  693.     x = event->xbutton.x / self->crEdit.fontSize;
  694.     y = event->xbutton.y / self->crEdit.fontSize;
  695.  
  696.     debug2("SelectEndAc() %dx%d\n",x,y);
  697.  
  698.     if (x >= self->crEdit.map->mapx )
  699.     x = self->crEdit.map->mapx - 1;
  700.     if (x < 0)
  701.     x = 0;
  702.  
  703.     if (y >= self->crEdit.map->mapy )
  704.     y = self->crEdit.map->mapy - 1;
  705.     if (y < 0)
  706.     y = 0;
  707.  
  708.     /*** fill the call strcture ***/
  709.     if(self->crEdit.selectArea) {
  710.     SegToRec(&self->crEdit.seg,&call.rect);
  711.     } else {
  712.     call.rect.x = x;
  713.     call.rect.y = y;
  714.     call.rect.width = 0;
  715.     call.rect.height = 0;
  716.     }
  717.     call.map = self->crEdit.map;
  718.     call.z = 0;
  719.  
  720.     XtCallCallbackList(w,self->crEdit.selectCallbacks,(XtPointer)&call);
  721. }
  722.  
  723. /* 
  724.  * action: 
  725.  */
  726. static void PropsAc(Widget w, XEvent * event, 
  727.              String * argv, Cardinal * argc)
  728. {
  729.     CrEditWidget self = (CrEditWidget)w;
  730.     int x, y;
  731.     struct CrEditCall call;
  732.  
  733.     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
  734.     x = event->xbutton.x / self->crEdit.fontSize;
  735.     y = event->xbutton.y / self->crEdit.fontSize;
  736.  
  737.     /*** fill the call strcture ***/
  738.     call.rect.x = x;
  739.     call.rect.y = y;
  740.     call.rect.width = 0;
  741.     call.rect.height = 0;
  742.     call.map = self->crEdit.map;
  743.     call.z = self->crEdit.stacking ? CalcIndex 
  744.     (w,event->xbutton.x, event->xbutton.y) : 0;
  745.  
  746.     XtCallCallbackList(w,self->crEdit.propsCallbacks,(XtPointer)&call);
  747. }
  748.  
  749. /* 
  750.  * action: delete object from map 
  751.  */
  752. static void DeleteAc(Widget w, XEvent * event, 
  753.              String * argv, Cardinal * argc)
  754. {
  755.     CrEditWidget self = (CrEditWidget)w;
  756.     int x, y;
  757.     static int oldx, oldy;
  758.     struct CrEditCall call;
  759.  
  760.     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
  761.     x = event->xbutton.x / self->crEdit.fontSize;
  762.     y = event->xbutton.y / self->crEdit.fontSize;
  763.  
  764.     if (!(event->type == MotionNotify  && x == oldx && y == oldy)) {
  765.     /*** fill the call strcture ***/
  766.     call.rect.x = x;
  767.     call.rect.y = y;
  768.     call.rect.width = 0;
  769.     call.rect.height = 0;
  770.     call.map = self->crEdit.map;
  771.     call.z = self->crEdit.stacking ? CalcIndex 
  772.         (w,event->xbutton.x, event->xbutton.y) : 0;
  773.  
  774.     XtCallCallbackList(w,self->crEdit.deleteCallbacks,(XtPointer)&call);
  775.     UpdatePosition(w,x,y,False);
  776.     }
  777.     oldx = x;
  778.     oldy = y;
  779. }
  780.  
  781. /* 
  782.  * action: feed point
  783.  */
  784. static void FeedAc (Widget w, XEvent * event, String * argv, Cardinal * argc)
  785. {
  786.     CrEditWidget self = (CrEditWidget)w;
  787.     int x, y;
  788.     static int oldx, oldy;
  789.     struct CrEditCall call;
  790.     
  791.     x = event->xbutton.x / self->crEdit.fontSize;
  792.     y = event->xbutton.y / self->crEdit.fontSize;
  793.  
  794.     if (!(event->type == MotionNotify  && x == oldx && y == oldy)) {
  795.     /*** fill the call strcture ***/
  796.     call.rect.x = x;
  797.     call.rect.y = y;
  798.     call.rect.width = 0;
  799.     call.rect.height = 0;
  800.     call.map = self->crEdit.map;
  801.     call.z = self->crEdit.stacking ? CalcIndex 
  802.         (w,event->xbutton.x, event->xbutton.y) : 0;
  803.  
  804.     XtCallCallbackList(w,self->crEdit.feedCallbacks,(XtPointer)&call);
  805.     }
  806.  
  807.     oldx = x;
  808.     oldy = y;
  809. }
  810.  
  811. /*
  812.  * action: resize to directions
  813.  */
  814. static void ResizeAc (Widget w, XEvent * e, String * argv, Cardinal * argc)
  815. {
  816.     CrEditWidget self = (CrEditWidget)w;
  817.     struct CrEditCall call;
  818.     char buf[BUFSIZ];
  819.  
  820.     call.map = self->crEdit.map;
  821.     call.rect.x = 0;
  822.     call.rect.y = 0;
  823.     call.rect.width = self->crEdit.map->mapx;
  824.     call.rect.height = self->crEdit.map->mapy;
  825.     call.z = 0;
  826.     if (argv) {
  827.     if (!strcmp (argv[0], "right")) {
  828.         call.rect.width++;
  829.     } else if (!strcmp (argv[0], "left")) {
  830.         call.rect.width--;
  831.     } else if (!strcmp (argv[0], "down")) {
  832.         call.rect.height++;
  833.     } else if (!strcmp (argv[0], "up")) {
  834.         call.rect.height--;
  835.     } else {
  836.         sprintf(buf,"bad argument %s",argv[0]);
  837.         CnvWarn(w,buf);
  838.     }
  839.     }
  840.     XtCallCallbackList(w,self->crEdit.alignCallbacks,(XtPointer)&call);
  841. }
  842.  
  843. /*
  844.  * action: scroll around to directions
  845.  */
  846. static void ScrollAc (Widget w, XEvent * e, String * argv, Cardinal * argc)
  847. {
  848.     CrEditWidget self = (CrEditWidget)w;
  849.     struct CrEditCall call;
  850.     char buf[BUFSIZ];
  851.  
  852.     call.map = self->crEdit.map;
  853.     call.rect.x = 0;
  854.     call.rect.y = 0;
  855.     call.rect.width = self->crEdit.map->mapx;
  856.     call.rect.height = self->crEdit.map->mapy;
  857.     call.z = 0;
  858.  
  859.     /*
  860.     debug4("CrEdit::ScrollAc() by %dx%d+%d+%d",call->rect.width,
  861.        call->rect.height,call->rect.x,call->rect.y); */
  862.  
  863.     if (argv) {
  864.     if (!strcmp (argv[0], "right")) {
  865.         call.rect.x++;
  866.     } else if (!strcmp (argv[0], "left")) {
  867.         call.rect.x--;
  868.     } else if (!strcmp (argv[0], "down")) {
  869.         call.rect.y++;
  870.     } else if (!strcmp (argv[0], "up")) {
  871.         call.rect.y--;
  872.     } else {
  873.         sprintf(buf,"bad argument %s",argv[0]);
  874.         CnvWarn(w,buf);
  875.     }
  876.     XtCallCallbackList(w,self->crEdit.alignCallbacks,(XtPointer)&call);
  877.     }
  878. }
  879.     
  880. /*
  881.  * action: move clipped window in viewport
  882.  */
  883. static void MoveAc (Widget w, XEvent * e, String * argv, Cardinal * argc)
  884. {
  885.     /* CrEditWidget self = (CrEditWidget)w; */
  886.     Widget horizontal, vertical;
  887.  
  888.     if (argv) {
  889.     horizontal = XtNameToWidget (XtParent (w), "horizontal");
  890.     vertical = XtNameToWidget (XtParent (w), "vertical");
  891.  
  892.     if (!strcmp (argv[0], "right")) {
  893.         String argv[1];
  894.         argv[0] = XtNewString ("Forward");
  895.         XtCallActionProc (horizontal, "StartScroll", e, argv, 1);
  896.         XtFree (argv[0]);
  897.         argv[0] = XtNewString ("Proportional");
  898.         XtCallActionProc (horizontal, "NotifyScroll", e, argv, 1);
  899.         XtFree (argv[0]);
  900.         XtCallActionProc (horizontal, "EndScroll", e, NULL, 0);
  901.     } else if (!strcmp (argv[0], "left")) {
  902.         String argv[1];
  903.         argv[0] = XtNewString ("Backward");
  904.         XtCallActionProc (horizontal, "StartScroll", e, argv, 1);
  905.         XtFree (argv[0]);
  906.         argv[0] = XtNewString ("Proportional");
  907.         XtCallActionProc (horizontal, "NotifyScroll", e, argv, 1);
  908.         XtFree (argv[0]);
  909.         XtCallActionProc (horizontal, "EndScroll", e, NULL, 0);
  910.     } else if (!strcmp (argv[0], "down")) {
  911.         String argv[1];
  912.         argv[0] = XtNewString ("Forward");
  913.         XtCallActionProc (vertical, "StartScroll", e, argv, 1);
  914.         XtFree (argv[0]);
  915.         argv[0] = XtNewString ("Proportional");
  916.         XtCallActionProc (vertical, "NotifyScroll", e, argv, 1);
  917.         XtFree (argv[0]);
  918.         XtCallActionProc (vertical, "EndScroll", e, NULL, 0);
  919.     } else if (!strcmp (argv[0], "up")) {
  920.         String argv[1];
  921.         argv[0] = XtNewString ("Backward");
  922.         XtCallActionProc (vertical, "StartScroll", e, argv, 1);
  923.         XtFree (argv[0]);
  924.         argv[0] = XtNewString ("Proportional");
  925.         XtCallActionProc (vertical, "NotifyScroll", e, argv, 1);
  926.         XtFree (argv[0]);
  927.         XtCallActionProc (vertical, "EndScroll", e, NULL, 0);
  928.     }
  929.     }
  930. }
  931.  
  932. /**********************************************************************
  933.  * members
  934.  **********************************************************************/
  935.  
  936. static void ClassInitialize() 
  937. {
  938.     debug0("CrEdit-ClassInitialize()\n");
  939.  
  940. }
  941.  
  942. static void Initialize(Widget req,Widget new,Arg args[],Cardinal *num)
  943.     CrEditWidget self = (CrEditWidget)new;
  944.     
  945.     debug1("CrEdit-%s-Initialize()\n",XtName(new));
  946.  
  947.     /*** allocate gc ***/
  948.     self->crEdit.gc = GCCreate (new);
  949.     self->crEdit.fontSize = FONTSIZE;
  950.     SetSize(new);
  951.     BorderOff(new);
  952. }
  953.  
  954. static void Destroy(Widget w)
  955. {
  956.     CrEditWidget self = (CrEditWidget)w;
  957.     debug1("CrEdit-%s-Destroy()\n",XtName(w));
  958.     XtReleaseGC(w,self->crEdit.gc);
  959. }
  960.  
  961. static void Resize(Widget w)
  962. {
  963.     /* CrEditWidget self = (CrEditWidget)w; */
  964.     debug1("CrEdit-%s-Resize()\n",XtName(w));
  965.     SetSize(w);
  966. }
  967.  
  968. static void Redisplay(Widget w,XEvent *event,Region region)
  969. {
  970.     CrEditWidget self = (CrEditWidget)w;
  971.     XRectangle rect, new;
  972.  
  973.     if(!region) return;
  974.     XClipBox(region,&rect);
  975.     new.x = rect.x / self->crEdit.fontSize;
  976.     new.y = rect.y / self->crEdit.fontSize;
  977.     new.width = (rect.x + rect.width) / self->crEdit.fontSize - new.x + 1;
  978.     new.height = (rect.y + rect.height) / self->crEdit.fontSize - new.y + 1;
  979.  
  980.     debug5("CrEdit-%s-Expose() %dx%d+%d+%d\n",XtName(w),
  981.        new.width, new.height, new.x, new.y);
  982.  
  983.     DrawRectangle(w,new,False);
  984.     if (self->crEdit.selectArea)
  985.     DrawBorder(w, self->crEdit.seg, True);
  986. }
  987.  
  988. static Boolean SetValues(Widget cur,Widget req,Widget new,
  989.              Arg args[],Cardinal *num)
  990. {
  991.     Boolean redpy = False;
  992.  
  993.     CrEditWidget self = (CrEditWidget)new;
  994.     CrEditWidget old = (CrEditWidget)cur;
  995.     debug1("CrEdit-%s-SetValues()\n",XtName(new));
  996.     
  997.     /*** stacking change ***/
  998.     if(self->crEdit.stacking != old->crEdit.stacking) {
  999.     self->crEdit.fontSize = FONTSIZE + self->crEdit.stacking;
  1000.     SetSize(new);
  1001.     redpy = True;
  1002.     }
  1003.     /*** map change ***/
  1004.     if(self->crEdit.map != old->crEdit.map) {
  1005.     SetSize(new);
  1006.     redpy = True;
  1007.     }
  1008.     /*** weak wall change ***/
  1009.     if(self->crEdit.show_weak_walls != old->crEdit.show_weak_walls) {
  1010.     SetSize(new);
  1011.     redpy = True;
  1012.     }
  1013.     return redpy; /* redisplay */
  1014. }
  1015.  
  1016. /**********************************************************************
  1017.  * public
  1018.  **********************************************************************/
  1019.  
  1020. /*
  1021.  * member: draw rectangle part of w
  1022.  * rect  : rectangle, width = height = 10000 to draw all
  1023.  */
  1024. void CrEditRefresh(Widget w,XRectangle rect)
  1025. {
  1026.     CrEditWidget self = (CrEditWidget)w;
  1027.     if(!w) return;
  1028.  
  1029.  
  1030.     debug4("CrEditRefresh() %dx%d+%d+%d\n",
  1031.        rect.width,
  1032.        rect.height,
  1033.        rect.x,
  1034.        rect.y
  1035.        );
  1036.     /* for all */
  1037.     if(rect.width == 10000 && rect.height == 10000) {
  1038.     XClearWindow(XtDisplay(w),XtWindow(w));
  1039.     SetSize(w); /* for partially fix to sizing probem */
  1040.     }
  1041.     DrawRectangle(w,rect,False);
  1042.  
  1043.     if (self->crEdit.selectArea)
  1044.     DrawBorder(w, self->crEdit.seg, True);
  1045. }
  1046.  
  1047. /*
  1048.  * atc: True: selection-border drawing active, other no draw
  1049.  */
  1050. void CrEditBorderOff(Widget w)
  1051. {
  1052.     CrEditWidget self = (CrEditWidget)w;
  1053.  
  1054.     debug1("%s-CrEditBorderOff()\n",XtName(w));
  1055.     DrawBorder(w,self->crEdit.seg,False);
  1056.     BorderOff(w);
  1057. }
  1058.  
  1059. /*
  1060.  * member: 
  1061.  * rect  : 
  1062.  */
  1063. void CrEditSelect(Widget w,XRectangle rect)
  1064. {
  1065.     CrEditWidget self = (CrEditWidget)w;
  1066.     if(!w) return;
  1067.  
  1068.  
  1069.     debug4("CrEditRefresh() %dx%d+%d+%d\n",
  1070.        rect.width,
  1071.        rect.height,
  1072.        rect.x,
  1073.        rect.y
  1074.        );
  1075.     /* for all */
  1076.     if(rect.width == 10000 && rect.height == 10000) {
  1077.     XClearWindow(XtDisplay(w),XtWindow(w));
  1078.     SetSize(w); /* for partially fix to sizing probem */
  1079.     }
  1080.  
  1081.     if (self->crEdit.selectArea) {
  1082.     DrawBorder(w, self->crEdit.seg, False);
  1083.     self->crEdit.seg.x1 = rect.x;
  1084.     self->crEdit.seg.y1 = rect.y;
  1085.     self->crEdit.seg.x2 = rect.x + rect.width;
  1086.     self->crEdit.seg.y2 = rect.y + rect.height;
  1087.     DrawBorder(w, self->crEdit.seg, True);
  1088.     }
  1089. }
  1090.  
  1091. /*** end of CrEdit.c ***/
  1092.